﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.DataVisualization.Charting;
using System.Drawing;
using System.ServiceModel;
using GoodStuff.Heartbeat.Web.SensorServices;
using System.Net;
using GoodStuff.Web;

namespace GoodStuff.Heartbeat.Web
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            int hoursToShow = Page.GetParameter("span", 1);

            SensorServiceClient createdService = new SensorServiceClient();
            DateTime from = DateTime.Now.AddHours(-hoursToShow);
            DateTime to = DateTime.Now;

            ChartValueType valueType = (to - from) >= TimeSpan.FromHours(24) ? ChartValueType.DateTime : ChartValueType.Time;
            TimeSpan scaleDetail = TimeSpan.FromMinutes(5);
            if (hoursToShow < 4)
            {
                scaleDetail = TimeSpan.FromMinutes(1);
            }

            foreach(var sensor in createdService.GetSensorInfo())
            {
                Chart newChart = new Chart();
                graphs.Controls.Add(newChart);                

                var sensorvalues = createdService.GetSensorReadings(sensor.SensorID, sensor.ChannelID, from, to, scaleDetail);

                newChart.ImageType = ChartImageType.Png;                
                newChart.ID = "newChart" + sensor.SensorID.ToString();
                newChart.ChartAreas.Add(new ChartArea()
                {
                    Name = "ChartArea"
                });
                if(sensor.State != MonitorState.Healthy)
                {
                    newChart.ChartAreas[0].BackColor = Color.Red;
                }
                newChart.ChartAreas[0].AxisY.Title = sensor.Name;
                //newChart.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.LightGray;
                //newChart.ChartAreas[0].AxisX.MinorGrid.LineColor = Color.LightGray;
                //newChart.ChartAreas[0].AxisX.LineColor = Color.LightGray;
                newChart.ChartAreas[0].AxisY.LabelStyle.Font = new Font("Arial", 7);
                newChart.ChartAreas[0].AxisX.LabelStyle.Font = new Font("Arial", 7);
                newChart.Height = Unit.Pixel(200);
                newChart.Width = Unit.Pixel(500);

                newChart.Series.Add(new Series()
                {
                    ChartArea = "ChartArea",
                    Name = "Series2",
                    ChartType = SeriesChartType.Line,
                    XValueMember = "TimeStamp",
                    YValueMembers = "Average",
                    XValueType = valueType,
                    Color = Color.DarkGray
                }); 
                
                newChart.Series.Add(new Series()
                {
                    ChartArea = "ChartArea",
                    Name = "Series1",
                    ChartType = SeriesChartType.Line,
                    XValueMember = "TimeStamp",
                    YValueMembers = "Value",
                    XValueType = valueType,
                    BorderWidth = 2,
                    Color = Color.MediumBlue
                });
                
                newChart.Series[1]["EmptyPointValue"] = "Zero";
                newChart.Series[1].EmptyPointStyle.Color = System.Drawing.Color.Red;
                newChart.Series[1].EmptyPointStyle.BorderWidth = 2;
                newChart.Series[1].EmptyPointStyle.BorderDashStyle = ChartDashStyle.Dash;

                if (sensorvalues.Count() == 0)
                {
                    newChart.ChartAreas[0].AxisY.Maximum = 100;
                }

                newChart.DataSource = CollectReadings(sensorvalues, from, to);
                newChart.DataBind();
            }
        }        

        public class TimeBasedValue 
        {
            public DateTime TimeStamp { get; set; }
            public double Value { get; set; }
            public double Average { get; set; }
        }

        private IEnumerable<TimeBasedValue> CollectReadings(IEnumerable<SensorReading> sensorValues, DateTime start, DateTime end)
        {
            var average = (sensorValues.Count() > 0)?sensorValues.Average(p => p.Value):0;
            var results = sensorValues.Select(p => new TimeBasedValue() { TimeStamp = p.Timestamp, Value = p.Value, Average = average });         
            IList<TimeBasedValue> emptyList = new List<TimeBasedValue>();

            
            //now loop through the results to determine gaps for more than one minute and mark that as NaN.
            DateTime first = start;

            if (results.Count() == 0)
            {
                emptyList.Add(new TimeBasedValue() { TimeStamp = first, Value = 0 });
                emptyList.Add(new TimeBasedValue() { TimeStamp = first.AddMilliseconds(10), Value = Double.NaN });
            }

            foreach (var item in results.OrderBy(p => p.TimeStamp))
            {
                if (item.TimeStamp - first > TimeSpan.FromMinutes(10))
                {
                    //inject a new NaN.
                    emptyList.Add(new TimeBasedValue() { TimeStamp = first, Value = 0 });                   
                    emptyList.Add(new TimeBasedValue() { TimeStamp = first.AddMilliseconds(10), Value = Double.NaN });
                    emptyList.Add(new TimeBasedValue() { TimeStamp = item.TimeStamp.Subtract(TimeSpan.FromMilliseconds(10)), Value = 0 });                    
                }
                first = item.TimeStamp;
            }

            if (first < end.Subtract(TimeSpan.FromMinutes(10)))
            {
                //inject NaN
                //emptyList.Add(new TimeBasedValue() { TimeStamp = item.TimeStamp.AddMilliseconds(-10), Value = 0 });                   
                emptyList.Add(new TimeBasedValue() { TimeStamp = first.AddMilliseconds(10), Value = 0 });
                emptyList.Add(new TimeBasedValue() { TimeStamp = end, Value = Double.NaN });
                    
            }

            return results.Concat(emptyList).OrderBy(p => p.TimeStamp);
        }
    }
}